package com.jctrip.hotel.source.service.hworld.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.jctrip.hotel.common.util.BeanUtil;
import com.jctrip.hotel.domain.entity.*;
import com.jctrip.hotel.source.model.hworld.resp.*;
import com.jctrip.hotel.source.mq.HotelCallbackDefaultMqProducer;
import com.jctrip.hotel.source.service.basic.*;
import com.jctrip.hotel.source.xxl.hworld.thread.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jctrip.hotel.common.constant.RedisKeyConstant;
import com.jctrip.hotel.common.constant.XxlJobNameConstant;
import com.jctrip.hotel.common.enums.SourceEnum;
import com.jctrip.hotel.common.threadpool.XxlJobThreadPool;
import com.jctrip.hotel.common.util.JsonUtil;
import com.jctrip.hotel.common.util.RedisUtil;
import com.jctrip.hotel.domain.dao.HtHotelStdInfoDao;
import com.jctrip.hotel.source.client.HworldCallBackClient;
import com.jctrip.hotel.source.model.hworld.HworldCallBackRequestBody;
import com.jctrip.hotel.source.model.wehotel.req.HotelInfoData.MapDataResponse;
import com.jctrip.hotel.source.service.hworld.HworldService;
import com.jctrip.hotel.source.service.hworld.HworldTaskService;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author henry
 * @Date 2023/5/29 22:02
 * @Description
 */
@Service
@Slf4j
public class HworldTaskServiceImpl implements HworldTaskService {
    private static final long PUSH_EXPIRY = 1 * 60;
    /**
     * pop任务线程池
     */
    private static final XxlJobThreadPool hotelInfoPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_INFO_POP);
    private static final XxlJobThreadPool hotelRatesPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_RATES_POP);
    private static final XxlJobThreadPool hotelHotspotRatesPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_HOTSPOT_RATES_POP);
    private static final XxlJobThreadPool hotelLongRatesPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_LONGER_RATES_POP);
    private static final XxlJobThreadPool hotelRoomRepairPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_ROOM_REPAIR_POP);
    private static final XxlJobThreadPool hotelActivityRatesPopPool =
            new XxlJobThreadPool(XxlJobNameConstant.SYNC_HWORLD_ACTIVITY_RATES_POP);
    @Resource
    private HworldService hworldService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private HtHotelStdInfoService htHotelStdInfoService;
    @Resource
    private HtRoomTypeStdInfoService htRoomTypeStdInfoService;
    @Resource
    private HtHotelStdInfoDao htHotelStdInfoDao;
    @Resource
    private HtPriceCalendarService htPriceCalendarService;
    @Resource
    private HtSourceInfoService htSourceInfoService;
    @Autowired
    private HotelCallbackDefaultMqProducer hotelCallbackDefaultMqProducer;
    @Resource
    private HtHotelStdImageService htHotelStdImageService;
    @Resource
    private HtPriceCalendarHworldService htPriceCalendarHworldService;
    @Resource
    private HworldCallBackClient hworldCallBackClient;

    @Override
    public void syncHworldHotelIdListTask(String appId, String key, String hotelId) {
        List<HworldHotelDetail> hotelComplexList = hworldService.getHotelComplexList(appId, key, hotelId);
        for (HworldHotelDetail hworldHotelDetail : hotelComplexList) {
            HtHotelStdInfo htHotelStdInfo = parseHotelInfoData(hworldHotelDetail);
            // 基础信息
            htHotelStdInfoService.saveOrUpdate(htHotelStdInfo,
                    new LambdaQueryWrapper<HtHotelStdInfo>().eq(HtHotelStdInfo::getHotelId,
                            htHotelStdInfo.getHotelId()));
            for (HworldHoteRoomType hworldHoteRoomType : hworldHotelDetail.getHotelRoomTypeList()) {
                // 房型
                HtRoomTypeStdInfo roomType = new HtRoomTypeStdInfo();
                roomType.setHotelId(htHotelStdInfo.getHotelId());
                roomType.setRoomTypeCode(hworldHoteRoomType.getRoomTypeCode());
                roomType.setRoomTypeName(hworldHoteRoomType.getRoomTypeName());
                roomType.setRoomArea(String.valueOf(hworldHoteRoomType.getHotelArea()));
                roomType.setMaxCheckIn(hworldHoteRoomType.getMaxCheckInPeoNum());
                roomType.setFloor(hworldHoteRoomType.getFloorPlace());
                // todo
                Integer bedType = null;
                if (StringUtils.isNotBlank(hworldHoteRoomType.getBedType())) {
                    switch (hworldHoteRoomType.getBedType()) {
                        case "大床":
                            bedType = 0;
                            break;
                        case "单人床":
                            bedType = 1;
                            break;
                        case "双床":
                            bedType = 2;
                            break;
                        case "特大床":
                            bedType = 3;
                            break;
                        case "双人床":
                            bedType = 4;
                            break;
                        default:
                            bedType = 5;
                            break;
                    }
                }
                roomType.setBedType(bedType);
                roomType.setBedWidth(hworldHoteRoomType.getBedWidth());
                // todo
                //                                roomType.setAddBed(hworldHoteRoomType.getIsCanAddBed());
                Integer windowType = null;
                if (StringUtils.isNotBlank(hworldHoteRoomType.getIsHasWindow())) {
                    switch (hworldHoteRoomType.getIsHasWindow()) {
                        case "无窗":
                            windowType = 0;
                            break;
                        case "有窗":
                            windowType = 1;
                            break;
                        case "部分有窗":
                            windowType = 2;
                            break;
                        case "内景":
                            windowType = 3;
                            break;
                        default:
                            windowType = null;
                            break;
                    }
                }
                roomType.setWindowType(windowType);
                roomType.setExtra(JsonUtil.toString(hworldHoteRoomType));
                htRoomTypeStdInfoService.saveOrUpdate(roomType,
                        new LambdaQueryWrapper<HtRoomTypeStdInfo>().eq(HtRoomTypeStdInfo::getHotelId,
                                roomType.getHotelId())
                                .eq(HtRoomTypeStdInfo::getRoomTypeCode, roomType.getRoomTypeCode()));
            }
        }
    }

    @Override
    public void syncHworldHotelIdListTaskFastPush(String appId, String key) {
        if (redisUtil.setENx(RedisKeyConstant.HOTEL_MAIN_HWORLD_HOTELID_PUSH, PUSH_EXPIRY,
                RedisKeyConstant.HOTEL_MAIN_HWORLD_HOTELID_PUSH)) {
            List<HworldHotelInfo> hotelList = hworldService.getHotelList(appId, key);
            redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_HOTELID_LIST,
                    hotelList.stream().map(HworldHotelInfo::getHotelId).collect(Collectors.toList()));
        }
    }

    @Override
    public void syncHworldHotelIdListTaskFastPop(String appId, String key) {
        hotelInfoPopPool.execute(() -> new SyncHworldHotelIdTaskThread(appId, key));
    }

    @Override
    public void syncHworldRatesTaskPush() {
        try {
            List<HtHotelStdInfo> htHotelStdInfos = htHotelStdInfoDao.selectList(
                    new LambdaQueryWrapper<HtHotelStdInfo>().eq(HtHotelStdInfo::getSourceCode,
                            SourceEnum.HWORLD.getCode()));
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(htHotelStdInfos)
                    && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_RATES_LIST) <= 0) {
                redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_RATES_LIST,
                        htHotelStdInfos.stream().map(HtHotelStdInfo::getHotelId).collect(Collectors.toList()));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncHworldRatesTaskFastPop(String appId, String key, String memberLevel, Integer days, Map<String, String> rateCodeWithSourceIdMap) {
        hotelRatesPopPool.execute(
                () -> new SyncHworldRatesTaskThread(appId, key, memberLevel, days, rateCodeWithSourceIdMap));
    }

    @Override
    public void syncHworldLongerRatesPush() {
        try {
            List<HtHotelStdInfo> htHotelStdInfos = htHotelStdInfoDao.selectList(
                    new LambdaQueryWrapper<HtHotelStdInfo>().eq(HtHotelStdInfo::getSourceCode,
                            SourceEnum.HWORLD.getCode()));
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(htHotelStdInfos)
                    && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_LONGER_LIST) <= 0) {
                redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_LONGER_LIST,
                        htHotelStdInfos.stream().map(HtHotelStdInfo::getHotelId).collect(Collectors.toList()));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncHworldLongerRatesPop(String appId, String key, String memberLevel,
                                         Integer addDays, Integer days, Map<String, String> rateCodeWithSourceIdMap) {
        hotelLongRatesPopPool.execute(
                () -> new SyncHworldLongRatesTaskThread(appId, key, memberLevel, addDays, days, rateCodeWithSourceIdMap));
    }

    @Override
    public void syncHworldHotspotRatesTaskPush() {
        try {
            List<String> hotels = hworldCallBackClient.getHotspotHotels().stream()
                    .filter(e -> e.startsWith(SourceEnum.HWORLD.getCode())).collect(Collectors.toList());
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(hotels)
                    && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_HOTSPOT_RATES_LIST) <= 0) {
                redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_HOTSPOT_RATES_LIST,
                        new ArrayList<>(hotels));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncHworldHotspotRatesTaskFastPop(String appId, String key, String memberLevel, Integer days, Map<String, String> rateCodeWithSourceIdMap) {
        hotelHotspotRatesPopPool.execute(
                () -> new SyncHworldHotspotRatesTaskThread(appId, key, memberLevel, days, rateCodeWithSourceIdMap));
    }

    @Override
    public void syncHworldRatesTaskPop(String appId, String key, String hotelId, String start, String end,
                                       String memberLevel, Map<String, String> rateCodeWithSourceIdMap) {

        List<HworldRoomDTO> tmcAllRoomPrice = hworldService.getTMCAllRoomPrice(appId, key, hotelId, start, end, null, memberLevel);
        if (CollectionUtils.isEmpty(tmcAllRoomPrice)) {
            return;
        }
        List<String> rateCodes = new ArrayList<>(rateCodeWithSourceIdMap.keySet());
        tmcAllRoomPrice.forEach(tmcRoomPrice -> {
            if (!rateCodes.contains(tmcRoomPrice.getRateCode())) {
                return;
            }
            // 每日房间
            List<HworldPriceDailyDTO> priceDailyList = tmcRoomPrice.getPriceDailyList();

            // 每日房量信息
            List<HworldRoomCountDailyDTO> roomCountDailyList = tmcRoomPrice.getRoomCountDailyList();
            // 早餐信息
            HworldBreakFastDTO breakFastDTO = tmcRoomPrice.getMemberAndBreakFastList().stream()
                    .filter(hworldBreakFastDTO -> hworldBreakFastDTO.getMemberLevel().equals(memberLevel))
                    .findFirst().orElse(new HworldBreakFastDTO());
            roomCountDailyList.forEach(hworldRoomCount -> {
                // 同一个房型，同一天的价格
                HworldPriceDailyDTO hworldPriceDailyDTO = priceDailyList.stream()
                        .filter(priceDaily -> priceDaily.getBizDate().equals(hworldRoomCount.getBizDate())
                                && priceDaily.getRoomTypeId().equals(hworldRoomCount.getRoomTypeId())).findFirst().get();

                LambdaQueryWrapper<HtRoomTypeStdInfo> eq =
                        new LambdaQueryWrapper<HtRoomTypeStdInfo>().eq(HtRoomTypeStdInfo::getHotelId,
                                hworldService.parseInnId(hotelId))
                                .eq(HtRoomTypeStdInfo::getRoomTypeCode, hworldRoomCount.getRoomTypeId());
                HtRoomTypeStdInfo roomTypeStdInfo = htRoomTypeStdInfoService.getOne(eq);

                // build 参数
                HtPriceCalendarHworld htPriceCalendarHworld = new HtPriceCalendarHworld();
                htPriceCalendarHworld.setHotelId(hworldService.parseInnId(hotelId));
                htPriceCalendarHworld.setRoomTypeCode(hworldRoomCount.getRoomTypeId());
                htPriceCalendarHworld.setRoomTypeName(roomTypeStdInfo != null ? roomTypeStdInfo.getRoomTypeName() : null);
                htPriceCalendarHworld.setCalDate(hworldRoomCount.getBizDate());
                htPriceCalendarHworld.setQuota(hworldRoomCount.getAvailableCount());
                htPriceCalendarHworld.setCurrencyCode(hworldPriceDailyDTO.getCurrencyCode());
                htPriceCalendarHworld.setRetailPrice(hworldPriceDailyDTO.getMarketPrice());
                htPriceCalendarHworld.setPurchasePrice(hworldPriceDailyDTO.getCompanyToGroupPrice());
                htPriceCalendarHworld.setBreakfastCount(breakFastDTO.getBreakfastCount());
                HworldCancelDTO cancelInfo = tmcRoomPrice.getCancelInfo();
                if (cancelInfo != null) {
                    try {
                        if (cancelInfo.getIsCanCancel() != null) {
                            htPriceCalendarHworld.setCancelPolicyType(cancelInfo.getIsCanCancel() ? 3 : 1);
                        }
                        int lastCancelDay = cancelInfo.getLastCancelDay();
                        String date = new SimpleDateFormat("yyyy-MM-dd").format(
                                DateUtils.addDays(hworldRoomCount.getBizDate(), -lastCancelDay));
                        date = date + " " + cancelInfo.getLastCancelTime();
                        htPriceCalendarHworld.setLastCancelTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(date));
                    } catch (Exception e) {
                        log.error("syncHworldRatesTaskPop cancel rule error: ", e);
                    }
                    htPriceCalendarHworld.setCancelRule(JsonUtil.toString(cancelInfo));
                }
                htPriceCalendarHworld.setProductId(tmcRoomPrice.getRateCode());
                htPriceCalendarHworld.setSourceId(rateCodeWithSourceIdMap.get(tmcRoomPrice.getRateCode()));

                // 保存房态信息
                htPriceCalendarHworldService.saveOrUpdate(htPriceCalendarHworld,
                        new LambdaQueryWrapper<HtPriceCalendarHworld>().eq(HtPriceCalendarHworld::getHotelId,
                                htPriceCalendarHworld.getHotelId())
                                .eq(HtPriceCalendarHworld::getRoomTypeCode, htPriceCalendarHworld.getRoomTypeCode())
                                .eq(HtPriceCalendarHworld::getCalDate, htPriceCalendarHworld.getCalDate())
                                .eq(HtPriceCalendarHworld::getSourceId, htPriceCalendarHworld.getSourceId()));
            });
        });
    }

    @Override
    @Async("taskAsyncPool")
    public void syncHworldReateCallBackProcess(HworldCallBackRequestBody req) {
        String hotelId = req.getHotelId();
        req.setHotelId(hworldService.parseInnId(hotelId));
        // 通知到飞猪供应侧
        // 如果没有活动码标识 代表全部变动
        if (StringUtils.isBlank(req.getFlagInfo())) {
            hworldCallBackClient.callFezihuServer(req);
            String msg = JsonUtil.toString(req);
            if (StringUtils.isNotBlank(msg)) {
                hotelCallbackDefaultMqProducer.send(msg);
            }
        }
        // 将本地华住库存改为1
        htPriceCalendarHworldService.update(new LambdaUpdateWrapper<HtPriceCalendarHworld>()
                .set(HtPriceCalendarHworld::getQuota, 0)
                .eq(HtPriceCalendarHworld::getHotelId, req.getHotelId())
                .eq(StringUtils.isNotBlank(req.getRoomTypeId()), HtPriceCalendarHworld::getRoomTypeCode, req.getRoomTypeId())
                .likeRight(StringUtils.isNotBlank(req.getFlagInfo()), HtPriceCalendarHworld::getProductId, req.getFlagInfo())
                .between(HtPriceCalendarHworld::getCalDate, req.getStartDate(), req.getEndDate()));
        //        req.setHotelId(hotelId);
        //        // 通知到老的服务
        //        hworldCallBackClient.callOldSysServer(req);
        // 同步更新房态信息 todo
        //        this.syncHworldRatesTaskPop(sourceInfo.getSourceAppId(), sourceInfo.getSourceSecret(), req
        //        .getHotelId(),
        //                req.getStartDate(), req.getEndDate(),
        //                (String) JsonUtil.toMap(sourceInfo.getExtra()).get("memberLevel"));
    }

    @Override
    public void syncHworldRoomRepairPush() {
        try {
            List<String> hotels = hworldCallBackClient.getHotspotHotels().stream()
                    .filter(e -> e.startsWith(SourceEnum.HWORLD.getCode())).collect(Collectors.toList());
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(hotels)
                    && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_ROOM_REPAIR_LIST) <= 0) {
                redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_ROOM_REPAIR_LIST,
                        new ArrayList<>(hotels));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncHworldRoomRepairPop(String appId, String key, String memberLevel) {
        hotelRoomRepairPopPool.execute(
                () -> new SyncHworldRoomRepairTaskThread(appId, key, memberLevel));
    }

    @Override
    public void syncHworldRoomRepair(String appId, String key, String hotelId, String start, String end, String memberLevel) {
        // 将当前酒店下所有房型全部置为不可售
        htRoomTypeStdInfoService.update(null,
                new LambdaUpdateWrapper<HtRoomTypeStdInfo>()
                        .set(HtRoomTypeStdInfo::getRoomStatus, 0)
                        .eq(HtRoomTypeStdInfo::getHotelId, hotelId));
        HworldRoomDTO tmcRoomPrice = hworldService.getTMCRoomPrice(appId, key, hotelId, start, end, null, memberLevel);
        if (tmcRoomPrice == null) {
            return;
        }

        // 每日房量信息
        List<HworldRoomCountDailyDTO> roomCountDailyList = tmcRoomPrice.getRoomCountDailyList();

        roomCountDailyList.forEach(hworldRoomCount -> {
            // 将获取到房态的房型状态改为1
            htRoomTypeStdInfoService.update(null,
                    new LambdaUpdateWrapper<HtRoomTypeStdInfo>()
                            .set(HtRoomTypeStdInfo::getRoomStatus, 1)
                            .eq(HtRoomTypeStdInfo::getHotelId, hotelId)
                            .eq(HtRoomTypeStdInfo::getRoomTypeCode, hworldRoomCount.getRoomTypeId()));
        });
    }

    @Override
    public void syncHworldPicPush() {
        if (redisUtil.setENx(RedisKeyConstant.HOTEL_MAIN_HWORLD_PIC_PUSH, PUSH_EXPIRY,
                RedisKeyConstant.HOTEL_MAIN_HWORLD_PIC_PUSH)) {
            List<String> hotelIds = htHotelStdInfoDao.selectList(new LambdaQueryWrapper<HtHotelStdInfo>()
                    .eq(HtHotelStdInfo::getSourceCode, SourceEnum.HWORLD.getCode())
                    .eq(HtHotelStdInfo::getSourceStatus, 1)
                    .eq(HtHotelStdInfo::getBookStatus, 1))
                    .stream().map(HtHotelStdInfo::getHotelId)
                    .collect(Collectors.toList());
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(hotelIds)
                    && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_PIC_LIST) <= 0) {
                redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_PIC_LIST, new ArrayList<>(hotelIds));
            }

        }

    }

    @Override
    public void syncHworldPicPop(String sourceAppId, String sourceSecret) {
        hotelInfoPopPool.execute(() -> new SyncHworldPicTaskThread(sourceAppId, sourceSecret));

    }

    @Override
    public void syncHworldPic(String appId, String secret, String hotelId) {
        List<HworldHotelDetail> hotelComplexList = hworldService.getHotelComplexList(appId, secret, hworldService.parseHotelId(hotelId));
        for (HworldHotelDetail hotelData : hotelComplexList) {
            List<HworldHotelPhoto> hotelPhotoList = hotelData.getHotelPhotoList();
            // 门头照
            List<HtHotelStdImage> hotelOuterImages = htHotelStdImageService.list(new LambdaQueryWrapper<HtHotelStdImage>()
                    .eq(HtHotelStdImage::getHotelId, hotelId)
                    .eq(HtHotelStdImage::getImageType, 1));
            if (CollectionUtils.isEmpty(hotelOuterImages)) {

                HworldHotelPhoto outerPhoto = hotelPhotoList.stream().filter(htHotelPhoto -> htHotelPhoto.getRoomDesc().equals("门头照"))
                        .findAny().orElse(null);
                if (outerPhoto != null && !CollectionUtils.isEmpty(outerPhoto.getPhotoURL())) {
                    savePicInfo(hotelId, "", 1, outerPhoto.getPhotoURL().get(0), "");
                }
            }

            // 大堂照
            List<HtHotelStdImage> hotelInnerImages = htHotelStdImageService.list(new LambdaQueryWrapper<HtHotelStdImage>()
                    .eq(HtHotelStdImage::getHotelId, hotelId)
                    .eq(HtHotelStdImage::getImageType, 2));

            if (CollectionUtils.isEmpty(hotelInnerImages)) {
                List<HworldHotelPhoto> innerPhoto = hotelPhotoList.stream().filter(htHotelPhoto -> htHotelPhoto.getRoomDesc().equals("精选照片") ||
                        htHotelPhoto.getRoomDesc().equals("商务休息区") || htHotelPhoto.getRoomDesc().equals("精选图片")
                        || htHotelPhoto.getRoomDesc().equals("其他"))
                        .collect(Collectors.toList());
                Optional.ofNullable(innerPhoto).orElse(new ArrayList<>()).forEach(e -> {
                    Optional.ofNullable(e.getPhotoURL()).orElse(new ArrayList<>()).forEach(innerUrl -> {
                        savePicInfo(hotelId, "", 2, innerUrl, "");
                    });
                });

            }

            // 房型图
            List<HworldHoteRoomType> hotelRoomTypeList = hotelData.getHotelRoomTypeList();
            Optional.ofNullable(hotelRoomTypeList).orElse(new ArrayList<>())
                    .forEach(htRoomTypeInfo -> {
                        List<HtHotelStdImage> roomImages = htHotelStdImageService.list(new LambdaQueryWrapper<HtHotelStdImage>()
                                .eq(HtHotelStdImage::getHotelId, hotelId)
                                .eq(HtHotelStdImage::getImageType, 3)
                                .eq(HtHotelStdImage::getRoomTypeCode, htRoomTypeInfo.getRoomTypeCode())
                        );
                        if (CollectionUtils.isEmpty(roomImages)) {
                            savePicInfo(hotelId, htRoomTypeInfo.getRoomTypeCode(), 3, htRoomTypeInfo.getRoomTypePhotoUrl(), "");
                        }
                    });
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ignore) {
        }
    }

    @Override
    public void syncHworldActivityRatesTaskPop(String sourceAppId, String sourceSecret, String memberLevel, Integer days) {
        hotelActivityRatesPopPool.execute(() -> new SyncHworldActivityRatesTaskThread(sourceAppId, sourceSecret, memberLevel, days));
    }

    @Override
    public void syncHworldActivityRatesTaskPush() {
        try {
            if (redisUtil.setENx(RedisKeyConstant.HOTEL_MAIN_HWORLD_ACTIVITY_RATES_PUSH, PUSH_EXPIRY,
                    RedisKeyConstant.HOTEL_MAIN_HWORLD_ACTIVITY_RATES_PUSH)) {
                List<HtHotelStdInfo> htHotelStdInfos = htHotelStdInfoDao.selectList(
                        new LambdaQueryWrapper<HtHotelStdInfo>().eq(HtHotelStdInfo::getSourceCode, SourceEnum.HWORLD.getCode())
                                .eq(HtHotelStdInfo::getSourceStatus, 1)
                                .eq(HtHotelStdInfo::getBookStatus, 1));
                if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(htHotelStdInfos)
                        && redisUtil.lGetListSize(RedisKeyConstant.HOTEL_MAIN_HWORLD_ACTIVITY_RATES_LIST) <= 0) {
                    redisUtil.leftPushAll(RedisKeyConstant.HOTEL_MAIN_HWORLD_ACTIVITY_RATES_LIST,
                            htHotelStdInfos.stream().map(HtHotelStdInfo::getHotelId).collect(Collectors.toList()));
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    // todo 活动价落库xxl ， 废弃，合并到会员价落库方法中
    @Override
    public void syncHworldActivityRatesTask(String sourceAppId, String sourceSecret, String hotelId, String startDate, String endDate, String memberLevel) {
        List<HworldRoomDTO> roomRateList = hworldService.getTMCAllRoomPrice(sourceAppId, sourceSecret, hotelId, startDate, endDate, null, memberLevel);

        if (CollectionUtils.isEmpty(roomRateList)) {
            return;
        }
        roomRateList.forEach(tmcRoomPrice -> {
            // 会员价跳过
            if (tmcRoomPrice.getTagList().contains("Base")) {
                return;
            }
            // 每日房间
            List<HworldPriceDailyDTO> priceDailyList = tmcRoomPrice.getPriceDailyList();

            // 每日房量信息
            List<HworldRoomCountDailyDTO> roomCountDailyList = tmcRoomPrice.getRoomCountDailyList();
            // 早餐信息
            HworldBreakFastDTO breakFastDTO = tmcRoomPrice.getMemberAndBreakFastList().stream()
                    .filter(hworldBreakFastDTO -> hworldBreakFastDTO.getMemberLevel().equals(memberLevel))
                    .findFirst().orElse(new HworldBreakFastDTO());
            roomCountDailyList.forEach(hworldRoomCount -> {
                // 同一个房型，同一天的价格
                HworldPriceDailyDTO hworldPriceDailyDTO = priceDailyList.stream()
                        .filter(priceDaily -> priceDaily.getBizDate().equals(hworldRoomCount.getBizDate())
                                && priceDaily.getRoomTypeId().equals(hworldRoomCount.getRoomTypeId())).findFirst().get();

                LambdaQueryWrapper<HtRoomTypeStdInfo> eq =
                        new LambdaQueryWrapper<HtRoomTypeStdInfo>().eq(HtRoomTypeStdInfo::getHotelId,
                                hworldService.parseInnId(hotelId))
                                .eq(HtRoomTypeStdInfo::getRoomTypeCode, hworldRoomCount.getRoomTypeId());
                HtRoomTypeStdInfo roomTypeStdInfo = htRoomTypeStdInfoService.getOne(eq);

                // build 参数
                HtPriceCalendarHworld htPriceCalendarHworld = new HtPriceCalendarHworld();
                htPriceCalendarHworld.setHotelId(hworldService.parseInnId(hotelId));
                htPriceCalendarHworld.setRoomTypeCode(hworldRoomCount.getRoomTypeId());
                htPriceCalendarHworld.setRoomTypeName(roomTypeStdInfo != null ? roomTypeStdInfo.getRoomTypeName() : null);
                htPriceCalendarHworld.setCalDate(hworldRoomCount.getBizDate());
                htPriceCalendarHworld.setQuota(hworldRoomCount.getAvailableCount());
                htPriceCalendarHworld.setCurrencyCode(hworldPriceDailyDTO.getCurrencyCode());
                htPriceCalendarHworld.setRetailPrice(hworldPriceDailyDTO.getMarketPrice());
                htPriceCalendarHworld.setPurchasePrice(hworldPriceDailyDTO.getCompanyToGroupPrice());
                htPriceCalendarHworld.setBreakfastCount(breakFastDTO.getBreakfastCount());
                HworldCancelDTO cancelInfo = tmcRoomPrice.getCancelInfo();
                if (cancelInfo != null) {
                    try {
                        if (cancelInfo.getIsCanCancel() != null) {
                            htPriceCalendarHworld.setCancelPolicyType(cancelInfo.getIsCanCancel() ? 3 : 1);
                        }
                        int lastCancelDay = cancelInfo.getLastCancelDay();
                        String date = new SimpleDateFormat("yyyy-MM-dd").format(
                                DateUtils.addDays(hworldRoomCount.getBizDate(), -lastCancelDay));
                        date = date + " " + cancelInfo.getLastCancelTime();
                        htPriceCalendarHworld.setLastCancelTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(date));
                    } catch (Exception e) {
                        log.error("syncHworldRatesTaskPop cancel rule error: ", e);
                    }
                    htPriceCalendarHworld.setCancelRule(JsonUtil.toString(cancelInfo));
                }

                htPriceCalendarHworld.setProductId(tmcRoomPrice.getRateCode());
                // 保存房态信息
                htPriceCalendarHworldService.saveOrUpdate(htPriceCalendarHworld,
                        new LambdaQueryWrapper<HtPriceCalendarHworld>().eq(HtPriceCalendarHworld::getHotelId,
                                htPriceCalendarHworld.getHotelId())
                                .eq(HtPriceCalendarHworld::getRoomTypeCode, htPriceCalendarHworld.getRoomTypeCode())
                                .eq(HtPriceCalendarHworld::getCalDate, htPriceCalendarHworld.getCalDate())
                                .eq(HtPriceCalendarHworld::getSourceId, htPriceCalendarHworld.getSourceId()));

            });
        });

    }

    private void savePicInfo(String hotelId, String roomTypeCode, Integer type, String sourceUrl, String imageUrl) {
        HtHotelStdImage image = new HtHotelStdImage();
        image.setHotelId(hotelId);
        image.setRoomTypeCode(roomTypeCode);
        image.setImageType(type);
        image.setSourceUrl(sourceUrl);
        image.setImageUrl(imageUrl);
        htHotelStdImageService.save(image);
    }

    private HtHotelStdInfo parseHotelInfoData(HworldHotelDetail hotelData) {
        if (hotelData == null) {
            return null;
        }
        HtHotelStdInfo hotelInfoData = new HtHotelStdInfo();
        hotelInfoData.setSourceCode(SourceEnum.HWORLD.getCode());
        hotelInfoData.setHotelId(hworldService.parseInnId(hotelData.getHotelId()));
        hotelInfoData.setHotelName(hotelData.getHotelName());
        hotelInfoData.setHotelNameEn(hotelData.getHotelNameEn());
        if (hotelData.getBrandCode() != null) {
            hotelInfoData.setBrandCode(hotelData.getBrandCode().toString());

        }
        hotelInfoData.setBrandName(hotelData.getBrandName());
        hotelInfoData.setHotelAddress(hotelData.getHotelAddress());
        hotelInfoData.setHotelAddressEn(hotelData.getHotelAddressEn());
        hotelInfoData.setHotelTel(hotelData.getHotelTelephone());
        String cityName = hotelData.getCityName();
        if (StringUtils.isNotBlank(cityName) && cityName.endsWith("市")) {
            cityName = cityName.substring(0, cityName.length() - 1);
        }
        hotelInfoData.setCityName(cityName);
        hotelInfoData.setIntroduction(hotelData.getHotelWordIntroduce());
        hotelInfoData.setBookStatus(1);
        if (hotelData.getIsOpening() != null && false == hotelData.getIsOpening()) {
            hotelInfoData.setBookStatus(0);
        }
        hotelInfoData.setSupportRestaurant(0);
        if (!CollectionUtils.isEmpty(hotelData.getHotelServiceList())) {
            List<HworldHoteServiceDTO> dtoList = hotelData.getHotelServiceList().stream()
                    .filter(hworldHoteServiceDTO -> hworldHoteServiceDTO.getChildClassType().equals("4")).collect(
                            Collectors.toList());
            if (!CollectionUtils.isEmpty(dtoList)) {
                hotelInfoData.setSupportRestaurant(1);
            }
        }
        hotelInfoData.setSupportForeignGuest(null);

        hotelInfoData.setLongitude(new BigDecimal(hotelData.getLongitude()));
        hotelInfoData.setLatitude(new BigDecimal(hotelData.getLatitude()));
        hotelInfoData.setMapPointType(3);
        MapDataResponse mapDataResponse = new MapDataResponse();
        mapDataResponse.setLag(hotelData.getLatitude() != null ? Double.parseDouble(hotelData.getLatitude()) : null);
        mapDataResponse.setLng(null != hotelData.getLongitude() ? Double.parseDouble(hotelData.getLongitude()) : null);
        mapDataResponse.setMapType(3);
        return hotelInfoData;
    }


}
